#lang scheme

(require "util-functions.scm")
(require lang/htdp-intermediate-lambda)

;; in-phase2-from? : Board -> Boolean
;; determines if this board is in the phase2-from state
(define (in-phase2-from? board)
  (and (symbol=? (state-name board) 'p2-origin)
       (empty? (sds1 board))))

(check-expect (in-phase2-from? test-board-p2-from)
              true)
(check-expect (in-phase2-from? test-board-p2-to)
              false)
(check-expect (in-phase2-from? test-board-p2-commence-attack)
              false)
(check-expect (in-phase2-from? test-board-p2-continue?)
              false)

;; in-phase2-to? : Board -> Boolean
;; determines if this board is in the phase2-to state
(define (in-phase2-to? board)
  (and (symbol=? (state-name board) 'p2-victim)
       (empty? (sds2 board))))

(check-expect (in-phase2-from? test-board-p2-from)
              false)
(check-expect (in-phase2-from? test-board-p2-to)
              true)
(check-expect (in-phase2-from? test-board-p2-commence-attack)
              false)
(check-expect (in-phase2-from? test-board-p2-continue?)
              false)

;; in-phase2-commence-attack? : Board -> Boolean
;; determines if this board is in the phase2-to state
(define (in-phase2-commence-attack? board)
  (and (symbol=? (state-name board) 'p2-victim)
       (symbol? (sds2 board))
       (symbol=? (sds2 board) 'commence-attack)))

(check-expect (in-phase2-from? test-board-p2-from)
              false)
(check-expect (in-phase2-from? test-board-p2-to)
              false)
(check-expect (in-phase2-from? test-board-p2-commence-attack)
              true)
(check-expect (in-phase2-from? test-board-p2-continue?)
              false)

;; in-phase2-continue?? : Board -> Boolean
;; determines if this board is in the phase2-to state
(define (in-phase2-continue?? board)
  (and (symbol=? (state-name board) 'p2-victim)
       (symbol? (sds2 board))
       (symbol=? (sds2 board) 'continue?)))

(check-expect (in-phase2-from? test-board-p2-from)
              false)
(check-expect (in-phase2-from? test-board-p2-to)
              false)
(check-expect (in-phase2-from? test-board-p2-commence-attack)
              false)
(check-expect (in-phase2-from? test-board-p2-continue?)
              true)

;; phase2-handler : Board UI-Element -> Board
;; delegates the handling of phase2 out depending on the state of the board
;; and the type of UI-Element
(define (phase2-handler board action)
  (cond [(in-phase2-from? board) (from board action)]
        [(in-phase2-to? board) (to board action)]
        [(in-phase2-commence-attack? board) (commence-attack board action)]
        [(in-phase2-continue?? board) (continue? board action)]
        [else (error 'phase2-handler "The board is not in any Phase 2 sub-stage, phase is: "
                     (sds1 board))]))

(check-expect (phase2-handler running-game-p2-o next-phase)
              (from-buttons running-game-p2-o next-phase))
(check-expect (phase2-handler running-game-p2-victim next-phase)
              (to-buttons running-game-p2-victim next-phase))
(check-expect (phase2-handler running-game-p2-o g-ter-germany)
              (from-territories running-game-p2-o g-ter-germany))
(check-expect (phase2-handler running-game-p2-victim cancel)
              (to-buttons running-game-p2-victim next-phase))
(check-expect (phase2-handler running-game-p2-victim g-ter-germany)
              (to-territories running-game-p2-victim g-ter-germany))

;; phase2-handler-button : Board Button -> Board
;; delegates the handling of phase2 out depending on the state of the board
(define (phase2-handler-button board button)
  (cond [(in-phase2-from? board) (from-buttons board action)]
        [(in-phase2-to? board) (to-buttons board action)]
        [(in-phase2-commence-attack? board) (commence-attack-buttons board action)]
        [(in-phase2-continue?? board) (continue?-buttons board action)]
        [else (error 'phase2-handler "The board is not in any Phase 2 sub-
                                      stage, phase is: "
                     (first (board-state board)))]))

(check-expect (phase2-handler running-game-p2-o next-phase)
              (from-buttons running-game-p2-o next-phase))
(check-expect (phase2-handler running-game-p2-victim next-phase)
              (to-buttons running-game-p2-victim next-phase))
(check-expect (phase2-handler running-game-p2-victim cancel)
              (to-buttons running-game-p2-victim next-phase))

;; phase2-handler-territory : Board Territory -> Board
;; delegates the handling of phase2 out depending on the state of the board
(define (phase2-handler-territory board territory)
  (cond [(in-phase2-from? board) (from-territories board action)]
        [(in-phase2-to? board) (to-territories board action)]
        [(in-phase2-commence-attack? board) (commence-attack-territories board action)]
        [(in-phase2-continue?? board) (continue?-territories board action)]
        [else (error 'phase2-handler "The board is not in any Phase 2 sub-
                                      stage, phase is: "
                     (first (board-state board)))]))

(check-expect (phase2-handler running-game-p2-o g-ter-germany)
              (from-territories running-game-p2-o g-ter-germany))
(check-expect (phase2-handler running-game-p2-victim g-ter-germany)
              (to-territories running-game-p2-victim g-ter-germany))

;; from-buttons : Board Button -> Board
;; deals with button presses in the from part of phase2
(define (from-buttons board button)
  (cond [(next-phase-button? button) (goto-state board 3)]
        [else (error 'from
                     (string-append "Unhandled button in Phase 2 origin: "
                                    (symbol->string (button-name button))))]))

(check-error (from-buttons running-game-p2-o cancel)
             "Unhandled button in Phase 2 from: cancel")
(check-expect (from-buttons running-game-p2-o next-phase)
              running-game-p3-o)

;; from-territories : Board Territory -> Board
;; deals with territory clicks in the from part of phase2
(define (from-territories board territory)
  (cond [(territory-owned? territory (current-player board))
         (change-board-state board (list 'p2-victim
                                         (list territory)
                                         empty
                                         phase2-victim-buttons))]
        [else board]))

(check-expect (from running-game-p2-o g-ter-germany)
              running-game-p2-victim)
(check-expect (from running-game-p2-o g-ter-france)
              running-game-p2-o)

#|
g-state-p2-from
g-state-p2-to
g-state-p2-commence-attack
g-state-p2-continue?
|#

;; to-buttons : Board Button -> Board
;; deals with button presses in the phase 2 to state
(define (to-buttons board button)
  (cond [(next-phase-button? button) (goto-state board 3)]
        [(cancel-button? button) (goto-state board 2)]
        [else (error 'to-buttons (string-append "Unhandled button in Phase 2 to: "
                                                (symbol->string (button-name button))))]))

(check-expect (to test-board-p2-to g-ter-germany)
              test-board-p2-to)
(check-expect (to test-board-p2-to g-ter-france)
              test-board-p2-commence-attack)
(check-expect (to test-board-p2-to g-ter-canada)
              test-board-p2-to)

;; to-territories : Board Territory -> Board
;; deals with territory clicks in the phase 2 to state
(define (to-territories board territory)
  (cond [(territory-owned? territory (current-player board))
         (change-board-state board (list 'p2-victim
                                         (cons territory (state-data-slot1 board))
                                         'commence-attack
                                         phase2-victim-buttons))]
        [else board]))

(check-expect (to test-board-p2-to cancel)
              test-board-p2-from)
(check-expect (to test-board-p2-to next-phase)
              running-game-p3-o)

;; commence-attack-buttons : Board Button -> Board
;; deals with button presses in the phase 2 commence-attack state
;; In this state the game board is covered with a dice rolling display
;; which tells the user how many units they have left and how many their
;; opponnent has left and what the most recent dice roll was.
;; The user can only click to get through this stage.

;; continue?-buttons : Board Button -> Board
;; deals with button presses in the phase 2 commence-attack state
;;
;; In this state the game board is covered with a dice rolling display
;; which tells the user hwo many units they and their opponnents have left
;; and what the most recent dice roll was.  The user can choose to continue
;; or not.
(define (continue?-buttons board button)
  (cond [(button-name=? button 'yes) (roll-dice board)]
        [(button-name=? button 'no) (goto-state board 2)]
        [else (error 'continue?-buttons (string-append "Unhandled button in Phase 2
                                                        continue?: "
                                                       (symbol->string
                                                         (button-name button))))]))


;; WISHLIST
;; roll-dice : Board -> Board
;; creates random dice rolls for the current attack and stores them in the
;; state information
